<?php

namespace app\job\queue;


use think\facade\Queue;

/**
 * 队列逻辑类
 * 要使用队列的步骤如下：
 *  1. 配置队列配置文件，配置文件位置在 application/extra/queue.php，拷贝queue.php.backup修改为queue.php，并更改配置
 *      默认使用redis队列，更换不同环境需配置ip、账号等信息
 *  2. 确保cli模式下已开启work进程：  php think queue:work  --daemon --queue sanhengQueue
 *  3. 创建一个队列 QueueLogic::creaateQueue 传入处理该队列数据类名（$class_name）、要处理的数据（$job_data）、延迟时间（$delay）
 *  4. 实现处理类 新建一个 app\admin\jobs\$class_name 类，并实现 fire(Job $job, $job_data)方法，方法$job为任务对象类，$job_data
 *      为第三步中传入的第二个参数
 * Class QueueLogic
 * @package app\api\logic
 */
class QueueLogic
{
    /**
     * 队列名字 需要进入cli模式 执行如下
     *    php think queue:work  --daemon --queue sanhengQueue
     */
    const QUEUE_NAME = 'pdfQueue';
    /**
     * 处理任务类名前缀 后台的处理任务一律放在目录 app\admin\jobs 中
     */
    const QUEUE_JOBS_NAMESPACE_PREFIX = 'app\\job\\queue\\';

    /**
     * 创建一个队列 该队列的处理逻辑在 app\admin\jobs 下面，demo参考 app\admin\jobs\TestJob
     * @param string $class_name 处理类名字 不需要命名空间 只需要传类名 放在 app\admin\jobs目录下的类名
     *       该类只需要在fire方法里写处理逻辑即可
     * @param array $data 传入的数据数组 该数组会
     * @param int $delay 延迟时间 0 立即执行  传入大于等于0的数字代表 $delay秒后执行
     * @return bool 创建队列成功或失败
     */
    public static function creaateQueue(string $class_name, array $data, int $delay = 0, $name = ''): bool
    {
        $delay = (int)$delay;
        $delay < 0 && $delay = 0;
        // 1.当前任务将由哪个类来负责处理。
        //   当轮到该任务时，系统将生成一个该类的实例，并调用其 fire 方法
        $jobHandlerClassName = static::QUEUE_JOBS_NAMESPACE_PREFIX . $class_name;

        // 2.当前任务归属的队列名称，如果为新队列，会自动创建
        $jobQueueName = static::QUEUE_NAME;
        if (!empty($name)) {
            $jobQueueName = $name;
        }
        // 3.当前任务所需的业务数据 . 不能为 resource 类型，其他类型最终将转化为json形式的字符串
        //   ( jobData 为对象时，存储其public属性的键值对 )

        // 4.将该任务推送到消息队列，等待对应的消费者去执行
        if (0 === $delay) {
            //立即执行
            $isPushed = Queue::push($jobHandlerClassName, $data, $jobQueueName);
        } else {
            //延迟$delay秒后执行
            $isPushed = Queue::later($delay, $jobHandlerClassName, $data, $jobQueueName);
        }

        // database 驱动时，返回值为 1|false  ;   redis 驱动时，返回值为 随机字符串|false
        if ($isPushed !== false) {
            return true;
        } else {
            return false;
        }
    }
}